package com.lsh.oms.core.service.split.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.atp.api.model.base.ItemDc;
import com.lsh.atp.api.model.hold.HoldDetailQueryResponse;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.order.OrderDetail;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.proxy.service.AtpProxy;
import com.lsh.oms.core.proxy.service.MisProxy;
import com.lsh.oms.core.proxy.service.UserServiceProxy;
import com.lsh.oms.core.redis.RedisTemplate;
import com.lsh.oms.core.service.split.IOrderSplitService;
import com.lsh.oms.core.utils.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * Project Name: lsh-oms
 *
 * @author peter
 * @date 18/8/29
 * 北京链商电子商务有限公司
 * Package OrderSplitServiceImpl
 * desc:
 */
@Service
@Slf4j
public class OrderSplitServiceImpl implements IOrderSplitService {

    @Autowired
    private AtpProxy atpProxy;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MisProxy misProxy;
    @Autowired
    private UserServiceProxy userServiceProxy;

    @Override
    public Map<String, OrderHead> split(OrderHead parentOrderHead) {

        String supplierGroup = userServiceProxy.getSupplierGroup(parentOrderHead.getAddressCode().toString(), parentOrderHead.getVenderId());
        log.info(parentOrderHead.getOrderCode() + "-supplierGroup  split is " + supplierGroup);
        if (StringUtils.isEmpty(supplierGroup)) {
            log.info("{} supplierGroupid [{}],请求商城用户信息异常", "logSign", supplierGroup);
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "获取用户组信息失败 uid=" + parentOrderHead.getUserCode());
        }

        parentOrderHead.setSupplierGroupId(supplierGroup);

        Map<Long, Map<String, BigDecimal>> skuRuleMap = this.getSkuRuleMap(parentOrderHead);
        log.info("orderCode {} 的库存扣减信息 skuRuleMap {}", parentOrderHead.getOrderCode(), JSON.toJSONString(skuRuleMap));
//        Integer zoneCode = parentOrderHead.getRegionCode();
        Map<String, OrderHead> orderHeadSplit = new HashMap<>(30);
        for (OrderDetail parentOrderDetail : parentOrderHead.getDetails()) {

            String ext = parentOrderDetail.getDetailExt();
            JSONObject extJson = JSON.parseObject(ext);
            String providerId = extJson.getString("providerId");
            Long skuCode = parentOrderDetail.getSkuCode();
            Map<String, BigDecimal> ruleMap = skuRuleMap.get(skuCode);
            log.info("skuCode {} ruleMap {}", skuCode, JSON.toJSONString(ruleMap));
            if (CollectionUtils.isEmpty(ruleMap)) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "订单商品库存扣减信息不存在! sku_code=" + skuCode);
            }

            Iterator<Map.Entry<String, BigDecimal>> it = ruleMap.entrySet().iterator();
            Map<String, BigDecimal> providerPuleMap = new HashMap<>(6);
            while (it.hasNext()) {
                Map.Entry<String, BigDecimal> item = it.next();
                String supplyMarketDc = item.getKey();
                String[] splits = supplyMarketDc.split(":");
                if (splits.length != 3) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "库存扣减规则数据有误， supplyMarketDc = " + supplyMarketDc);
                }

                String market = splits[1];
                if (providerId.equals(market)) {
                    providerPuleMap.put(item.getKey(), item.getValue());
                }
            }

            if (providerPuleMap.size() != 1) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "订单商品库存扣减信息不存在!, sku_code= " + skuCode + " ruleMap is " + JSON.toJSONString(providerPuleMap));
            }

            String weightRule = providerPuleMap.entrySet().iterator().next().getKey();
            String[] weightRules = weightRule.split(":");
            // 云仓 冻品 物美 宁谷 按出货规则拆单
            String org = weightRules[0];
            String providerCode = weightRules[1];
            String dc = weightRules[2];
            // 拆单 维度
            String splitOrgProviderDc = org + ":" + providerCode + ":" + dc;
            log.info("ordercode {} dc {} split splitDcOrgProvider : " + splitOrgProviderDc, parentOrderHead.getOrderCode(), dc);
            OrderHead childrenOrderHead = orderHeadSplit.get(splitOrgProviderDc);
            if (childrenOrderHead == null) {
                childrenOrderHead = new OrderHead();
                BeanUtils.copyProperties(parentOrderHead, childrenOrderHead);

                childrenOrderHead.setId(null);
                childrenOrderHead.setOrderCode(IdGenerator.genId());
                childrenOrderHead.setParentOrderCode(parentOrderHead.getOrderCode());
                childrenOrderHead.setDetails(new ArrayList<OrderDetail>());

                orderHeadSplit.put(splitOrgProviderDc, childrenOrderHead);
            }

            OrderDetail childrenOrderDetail = new OrderDetail();

            BeanUtils.copyProperties(parentOrderDetail, childrenOrderDetail);
            childrenOrderDetail.setId(null);
            childrenOrderDetail.setOrderCode(childrenOrderHead.getOrderCode());
            childrenOrderHead.getDetails().add(parentOrderDetail);
        }

        return orderHeadSplit;
    }

    /**
     * @param order
     * @return
     */
    private Map<Long, Map<String, BigDecimal>> getSkuRuleMap(OrderHead order) {

        HoldDetailQueryResponse holdDetailQueryResponse = this.atpProxy.queryRuleQtyMap(order.getOrderCode(), order);
        List<ItemDc> items = holdDetailQueryResponse.getItems();
        if (CollectionUtils.isEmpty(items)) {
            log.info("查询库存扣减结果失败");
            return Collections.EMPTY_MAP;
        }

        Map<Long, Map<String, BigDecimal>> map = new HashMap<>(4);
        for (ItemDc item : items) {
            Long skuCode = item.getItemId();
            Map<String, BigDecimal> dcQty = map.get(skuCode);
            if (dcQty == null) {
                dcQty = new HashMap<>();
                map.put(skuCode, dcQty);
            }
            String splitDc = getSplitDc(order, item.getDc(), item.getSupplyMarket());

            if (StringUtils.isEmpty(splitDc)) {
                splitDc = item.getDc();
            }

            String splitRule = item.getSupplyId() + ":" + item.getSupplyMarket() + ":" + splitDc;

            BigDecimal qty = dcQty.get(splitRule);
            if (qty == null) {
                qty = item.getQty();
            } else {
                qty = qty.add(item.getQty());
            }

            dcQty.put(splitRule, qty);
        }

        return map;
    }

    /**
     * 先简单实现，后面请求策略服务
     *
     * @param head
     * @param atpDc
     * @param supplyMarket
     * @return
     */
    private String getSplitDc(OrderHead head, String atpDc, Integer supplyMarket) {
        //oms:split:dc:区域:货主:履约用户组:dc
        StringBuffer splitDcKey = new StringBuffer("oms:split:dc:");
        splitDcKey.append(head.getRegionCode()).append(":")
                .append(supplyMarket).append(":").append(head.getSupplierGroupId()).append(":").append(atpDc);
//        append(":").append(head.getSupplierGroupId())
//        List<StrategyAttr> straAttrValues = new ArrayList<>();
//        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.ZONE_CODE, String.valueOf(head.getRegionCode())));
//        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.DC, atpDc));
//        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.SUPPLY_MARKET, supplyMarket + ""));
//        straAttrValues.add(new StrategyAttr(StrategyRequestAttrType.SUPPLIER_GROUP, head.getSupplierGroupId()));
//
//        //调用策略服务 策略信息
//        StrategyRequest request = new StrategyRequest();
//        request.setChannelId(1);
//        request.setStraType(StraType.STRA_DELIVERY.getCode());
//        request.setStraAttrValues(straAttrValues);
        String splitDc = redisTemplate.get(splitDcKey.toString());

        if (StringUtils.isEmpty(splitDc)) {
            splitDc = atpDc;
        }

        return splitDc;
    }
}
